package hu.uszeged.inf.wlab.stunner.database.dtos;

import hu.uszeged.inf.wlab.stunner.utils.DiscoveryResult;

import java.io.Serializable;

import org.codehaus.jackson.annotate.JsonIgnore;

import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;

/**
 * Builder class to construct the data structure which represents a {@link hu.uszeged.inf.wlab.stunner.database.STUNnerContract.Discovery
 * Discovery} object.
 * 
 * @author szelezsant
 */
public class DiscoveryDTO implements Serializable, Parcelable {

	/**
	 * Creator used to regenerate original object.
	 */
	public static final Parcelable.Creator<DiscoveryDTO> CREATOR = new Parcelable.Creator<DiscoveryDTO>() {

		@Override
		public DiscoveryDTO createFromParcel(final Parcel source) {
			return new DiscoveryDTO(source);
		}

		@Override
		public DiscoveryDTO[] newArray(final int size) {
			return new DiscoveryDTO[size];
		}
	};

	/**
	 * Serialversion UID.
	 */
	private static final long serialVersionUID = 7943538191200263542L;

	/* mandatory fields */
	/** The latitude of the discovery location. */
	private double latitude;
	/** The longitude of the discovery location. */
	private double longitude;
	/** The timestamp of the discovery in milliseconds. */
	private long timeStamp;
	/** The corresponding result code of the discovery according to the {@link DiscoveryResult} enumeration. */
	private int discoveryResult;
	/** Flag to indicate if the record was marked by the user. */
	private boolean bookmarked;
	/** Flag to indicate if the record is waiting for uploading. */
	private boolean pending;

	/* optional fields */
	/** The identifier of the persisted record. */
	private Long identifier;
	/** The identifier of the assigned {@link hu.uszeged.inf.wlab.stunner.database.STUNnerContract.BatteryInfo BatteryInfo} object. */
	private Long batteryInfoId;
	/** The formatted local IP address. */
	private String localIP;
	/** The formatted public IP address. */
	private String publicIP;
	/** The decoded location data. */
	private String location;
	/** The identifier of the wifi info object. */
	private Long wifiInfoId;
	/** The identifier of the mobile info object. */
	private Long mobileInfoId;

	/** The wifi info dto. */
	private WifiInfoDTO wifiDTO;
	/** The mobile info dto. */
	private MobileNetInfoDTO mobileDTO;
	/** The battery info dto. */
	private BatteryInfoDTO batteryDTO;

	/**
	 * Constructor to initialize the default values of some attributes.
	 */
	public DiscoveryDTO() {
		localIP = "N/A";
		publicIP = "N/A";
		bookmarked = false;
		location = "N/A";
		pending = true;
	}

	/**
	 * Constructor used when recreating object from a parcel.
	 * 
	 * @param parcel - the parcel object to read the data back.
	 */
	public DiscoveryDTO(final Parcel parcel) {
		timeStamp = parcel.readLong();
		discoveryResult = parcel.readInt();
		latitude = parcel.readDouble();
		longitude = parcel.readDouble();
		identifier = parcel.readLong();
		localIP = parcel.readString();
		publicIP = parcel.readString();
		bookmarked = 1 == parcel.readInt();
		location = parcel.readString();
		batteryInfoId = parcel.readLong();
		wifiInfoId = parcel.readLong();
		mobileInfoId = parcel.readLong();
		pending = 1 == parcel.readInt();
	}

	/**
	 * Gets the latitude.
	 * 
	 * @return the latitude
	 */
	public double getLatitude() {
		return latitude;
	}

	/**
	 * Sets the latitude.
	 * 
	 * @param latitude the latitude to set
	 */
	public void setLatitude(final double latitude) {
		this.latitude = latitude;
	}

	/**
	 * Gets the longitude.
	 * 
	 * @return the longitude
	 */
	public double getLongitude() {
		return longitude;
	}

	/**
	 * Sets the longitude.
	 * 
	 * @param longitude the longitude to set
	 */
	public void setLongitude(final double longitude) {
		this.longitude = longitude;
	}

	/**
	 * Gets the timestamp.
	 * 
	 * @return the timeStamp
	 */
	public long getTimeStamp() {
		return timeStamp;
	}

	/**
	 * Sets the timestamp.
	 * 
	 * @param timeStamp the timeStamp to set
	 */
	public void setTimeStamp(final long timeStamp) {
		this.timeStamp = timeStamp;
	}

	/**
	 * Gets the result of the discovery.
	 * 
	 * @return the discoveryResult
	 */
	@JsonIgnore
	public DiscoveryResult getDiscoveryResult() {
		return DiscoveryResult.getByCode(discoveryResult);
	}

	/**
	 * Gets the result code of the discovery.
	 * 
	 * @return the discoveryResult
	 */
	public int getDiscoveryResultCode() {
		return discoveryResult;
	}

	/**
	 * Sets the resultCode of the discovery.
	 * 
	 * @param discoveryResultCode the code of the discoveryResult to set
	 */
	public void setDiscoveryResultCode(final int discoveryResultCode) {
		this.discoveryResult = discoveryResultCode;
	}

	/**
	 * Gets the identifier of the persisted record.
	 * 
	 * @return the identifier
	 */
	public Long getIdentifier() {
		return identifier;
	}

	/**
	 * Sets the identifier of the persisted record.
	 * 
	 * @param identifier the identifier to set
	 */
	public void setIdentifier(final Long identifier) {
		this.identifier = identifier;
	}

	/**
	 * Gets the local IP address.
	 * 
	 * @return the localIP
	 */
	public String getLocalIP() {
		return localIP;
	}

	/**
	 * Sets the local IP address.
	 * 
	 * @param localIP the localIP to set
	 */
	public void setLocalIP(final String localIP) {
		this.localIP = localIP;
	}

	/**
	 * Gets the public IP address.
	 * 
	 * @return the publicIP
	 */
	public String getPublicIP() {
		return publicIP;
	}

	/**
	 * Sets the public IP address.
	 * 
	 * @param publicIP the publicIP to set
	 */
	public void setPublicIP(final String publicIP) {
		this.publicIP = publicIP;
	}

	/**
	 * Gets the bookmarked flag.
	 * 
	 * @return the bookmarked
	 */
	@JsonIgnore
	public boolean isBookmarked() {
		return bookmarked;
	}

	/**
	 * Sets the bookmarked flag.
	 * 
	 * @param bookmarked the bookmarked to set
	 */
	@JsonIgnore
	public void setBookmarked(final boolean bookmarked) {
		this.bookmarked = bookmarked;
	}

	/**
	 * Gets the location string.
	 * 
	 * @return the location
	 */
	@JsonIgnore
	public String getLocation() {
		return location;
	}

	/**
	 * Sets the decoded location.
	 * 
	 * @param location the location to set
	 */
	@JsonIgnore
	public void setLocation(final String location) {
		this.location = location;
	}

	/**
	 * @return the batteryInfoId
	 */
	@JsonIgnore
	public Long getBatteryInfoId() {
		return batteryInfoId;
	}

	/**
	 * @param batteryInfoId the batteryInfoId to set
	 */
	@JsonIgnore
	public void setBatteryInfoId(final Long batteryInfoId) {
		this.batteryInfoId = batteryInfoId;
	}

	/**
	 * Checks if all of the mandatory data is present before the discovery could be persisted. You should always check this first.
	 * 
	 * @return true is all of the mandatory data is present, false otherwise.
	 */
	@JsonIgnore
	public boolean hasAllMandatoryData() {
		return 0 < discoveryResult && 0.0 < latitude && 0.0 < longitude && 0L < batteryInfoId;
	}

	/**
	 * @return the wifiInfoId
	 */
	@JsonIgnore
	public Long getWifiInfoId() {
		return wifiInfoId;
	}

	/**
	 * @param wifiInfoId the wifiInfoId to set
	 */
	@JsonIgnore
	public void setWifiInfoId(final Long wifiInfoId) {
		this.wifiInfoId = wifiInfoId;
	}

	/**
	 * @return the mobileInfoId
	 */
	@JsonIgnore
	public Long getMobileInfoId() {
		return mobileInfoId;
	}

	/**
	 * @param mobileInfoId the mobileInfoId to set
	 */
	@JsonIgnore
	public void setMobileInfoId(final Long mobileInfoId) {
		this.mobileInfoId = mobileInfoId;
	}

	/**
	 * @return the pending
	 */
	@JsonIgnore
	public boolean isPending() {
		return pending;
	}

	/**
	 * @param pending the pending to set
	 */
	@JsonIgnore
	public void setPending(final boolean pending) {
		this.pending = pending;
	}

	/**
	 * @return the wifiDTO
	 */
	public WifiInfoDTO getWifiDTO() {
		return wifiDTO;
	}

	/**
	 * @param wifiDTO the wifiDTO to set
	 */
	public void setWifiDTO(final WifiInfoDTO wifiDTO) {
		this.wifiDTO = wifiDTO;
	}

	/**
	 * @return the mobileDTO
	 */
	public MobileNetInfoDTO getMobileDTO() {
		return mobileDTO;
	}

	/**
	 * @param mobileDTO the mobileDTO to set
	 */
	public void setMobileDTO(final MobileNetInfoDTO mobileDTO) {
		this.mobileDTO = mobileDTO;
	}

	/**
	 * @return the batteryDTO
	 */
	public BatteryInfoDTO getBatteryDTO() {
		return batteryDTO;
	}

	/**
	 * @param batteryDTO the batteryDTO to set
	 */
	public void setBatteryDTO(final BatteryInfoDTO batteryDTO) {
		this.batteryDTO = batteryDTO;
	}

	/**
	 * Gets the android version code.
	 * 
	 * @return android API level.
	 */
	public int getAndroidVersion() {
		return Build.VERSION.SDK_INT;
	}

	/*
	 * (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return "DiscoveryDTO [latitude=" + latitude + ", longitude=" + longitude + ", timeStamp=" + timeStamp + ", discoveryResult="
				+ discoveryResult + ", bookmarked=" + bookmarked + ", pending=" + pending + ", identifier=" + identifier
				+ ", batteryInfoId=" + batteryInfoId + ", localIP=" + localIP + ", publicIP=" + publicIP + ", location=" + location
				+ ", wifiInfoId=" + wifiInfoId + ", mobileInfoId=" + mobileInfoId + "]";
	}

	@Override
	public int describeContents() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void writeToParcel(final Parcel dest, final int flags) {
		dest.writeLong(timeStamp);
		dest.writeInt(discoveryResult);
		dest.writeDouble(latitude);
		dest.writeDouble(longitude);
		dest.writeLong(identifier);
		dest.writeString(localIP);
		dest.writeString(publicIP);
		dest.writeInt(bookmarked ? 1 : 0);
		dest.writeString(location);
		dest.writeLong(batteryInfoId);
		dest.writeLong(wifiInfoId);
		dest.writeLong(mobileInfoId);
		dest.writeInt(pending ? 1 : 0);
	}
}
